<?php
namespace app\api\service\wine;

use app\api\model\Wx as WxModel;
use app\common\exception\BaseException;
use app\common\library\helper;
use app\common\service\BaseService;
use think\App;
use think\facade\Cache;

class Wechat extends BaseService{
    public $config;

    public function __construct()
    {
        parent::__construct();
        $this->config = WxModel::getWxappCache();
    }

    /**
     * 获取微信操作对象（单例模式）
     * @staticvar array $wechat 静态对象缓存对象
     * @param string $type 接口名称 ( Card|Custom|Device|Extend|Media|Oauth|Pay|Receive|Script|User )
     * @return array \Wehcat\WechatReceive 返回接口对接
     */
    public function & load_wechat(string $type = '')
    {
        static $wechat = array();
        $index = md5(strtolower($type));
        if (!isset($wechat[$index])) {
            // 定义微信公众号配置参数（这里是可以从数据库读取的哦）
            $wxgConfig = [
                'token'          => $this->config['token'],          // 填写你设定的key
                'appid'          => $this->config['appid'],          // 填写高级调用功能的app id, 请在微信开发模式后台查询
                'appsecret'      => $this->config['appsecret'],      // 填写高级调用功能的密钥
                'encodingaeskey' => $this->config['encodingaeskey'], // 填写加密用的EncodingAESKey（可选，接口传输选择加密时必需）
                'mch_id'          => $this->config['mch_id'],  // 微信支付，商户ID（可选）
                'partnerkey'      => $this->config['partnerkey'], // 微信支付，密钥（可选）
                'ssl_cer'         => $this->config['ssl_cer'], // 微信支付，双向证书（可选，操作退款或打款时必需）
                'ssl_key'         => $this->config['ssl_key'], // 微信支付，双向证书（可选，操作退款或打款时必需）
                'cachepath'       => $this->config['cachepath'], // 设置SDK缓存目录（可选，默认位置在Wechat/Cache下，请保证写权限）
            ];
            \Wechat\Loader::config($wxgConfig);
            $wechat[$index] = \Wechat\Loader::get($type);
        }
        return $wechat[$index];
    }

    // 关键词回复
    public function _keys($keys){
        $wechat = & $this->load_wechat('Receive');
        // 这里直接原样回复给微信(当然你需要根据业务需求来定制的)
        return $wechat->text($keys)->reply();
    }

    // 事件
    public function _event($event) {
        $wechat = & $this->load_wechat('Receive');
        switch ($event) {
            // 粉丝关注事件
            case 'subscribe':
                return $wechat->text('欢迎关注公众号！')->reply();
            // 粉丝取消关注
            case 'unsubscribe':
                exit("success");
            // 点击微信菜单的链接
            case 'click':
                return $wechat->text('你点了菜单链接！')->reply();
            // 微信扫码推事件
            case 'scancode_push':
                return $wechat->text('扫码完毕！')->reply();
            case 'scancode_waitmsg':
                $scanInfo = $wechat->getRev()->getRevScanInfo();
                return $wechat->text("你扫码的内容是:{$scanInfo['ScanResult']}")->reply();
            // 扫码关注公众号事件（一般用来做分销）
            case 'scan':
                return $wechat->text('欢迎扫码关注公众号！')->reply();
            default:
                return $wechat->text('未知事件！')->reply();
        }
    }

    // 图片消息
    public function _image(){
        // $wechat 中有获取图片的方法
        $wechat = & $this->load_wechat('Receive');
	    return $wechat->text('您发送了一张图片过来')->reply();
    }

    //
    public function _location(){
        $wechat = & $this->load_wechat('Receive');
        return $wechat->text('您发送了地理位置过来')->reply();
    }

    //
    public function _default(){
        $wechat = & $this->load_wechat('Receive');
        return $wechat->text('默认定义消息')->reply();
    }

    // 获取微信网页授权code的url值
    public function getWechatCode(string $REDIRECT_URI,string $state = '',int $scopeType = 0){
        $appid = $this->config['appid'];
        switch ($scopeType){
            case 0:
                $scope = 'snsapi_userinfo';
                break;
            case 1:
                $scope = 'snsapi_base';
                break;
        }
        if($state == ''){
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$REDIRECT_URI}&response_type=code&scope={$scope}#wechat_redirect";
        }else{
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$REDIRECT_URI}&response_type=code&scope={$scope}&state=$state#wechat_redirect";
        }
        return $url;
    }

    /**
     * 模拟GET请求 HTTPS的页面
     * @param string $url 请求地址
     * @param array $data
     * @return string $result
     * @throws BaseException
     */
    private function get(string $url, array $data = [])
    {
        // 处理query参数
        if (!empty($data)) {
            $url = $url . '?' . http_build_query($data);
        }
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
        $result = curl_exec($curl);
        if ($result === false) {
            throwError(curl_error($curl));
        }
        curl_close($curl);
        return $result;
    }
    /**
     * 数组转json
     * @param $data
     * @return string
     */
    private function jsonEncode($data)
    {
        return helper::jsonEncode($data, JSON_UNESCAPED_UNICODE);
    }

    /**
     * json转数组
     * @param $json
     * @return mixed
     */
    private function jsonDecode($json)
    {
        return helper::jsonDecode($json);
    }

    // 获取公众号的access_token
    private function getAccess_token()
    {
        $appId = $this->config['appid'];
        $appsecret = $this->config['appsecret'];
        $cacheKey = $appId . '@wxg_access_token';
        if (!Cache::instance()->get($cacheKey)) {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appsecret}";
            $access_tokenArr = $this->jsonDecode($this->get($url));
            if(array_key_exists('errcode',$access_tokenArr)){
                throwError("获取公众号的access_token获取失败，错误信息：{$access_tokenArr}");
            }
            $access_token = $access_tokenArr['access_token'];
            // 写入缓存
            Cache::instance()->set($cacheKey, $access_token, 6000);
        }
        return Cache::instance()->get($cacheKey);
    }

    // 微信公众号获取用户基本信息
    public function getGUserInfo(string $openid){
        $access_token = $this->getAccess_token();
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$openid}&lang=zh_CN";
        $gUserInfoArr = $this->jsonDecode($this->get($url));
        if(array_key_exists('errcode',$gUserInfoArr)){
            throwError("微信公众号获取用户基本信息失败，错误信息：{$gUserInfoArr}");
        }
        return $gUserInfoArr;
    }
}
